package storyteller;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

public class FlashAction {

  //``````````````````````
  // MEMBER VARIABLES
  //``````````````````````
  
  public FlashActionType Type;
  public Object Data;
  private Hashtable<String,String> _properties;

  //``````````````````````
  // CONSTRUCTOR
  //``````````````````````  

  public FlashAction()
  {
    init(FlashActionType.Text,"","");
  }
  
  public FlashAction(FlashActionType type, Object data)
  {
    init(type,data,"");
  }
  
  public FlashAction(FlashActionType type, Object data, String properties)
  {
    init(type,data,properties);
  }  
  
  private void init(FlashActionType type, Object data, String properties)
  {
    Type = type;
    Data = data;
    _properties = new Hashtable<String, String>();
    loadMultiProperties(properties);
  }
  
  public static FlashAction createText(String data, String properties)
  {
    return new FlashAction(FlashActionType.Text,data,properties);
  }

  public static FlashAction createLabel(String label, String properties)
  {
    return new FlashAction(FlashActionType.Label,label,properties);
  }
  
  public static FlashAction createMultiLabel(ArrayList<String> labels, String properties)
  {
    return new FlashAction(FlashActionType.MultiLabel,labels,properties);
  }
  
  public static FlashAction createMultiText(ArrayList<String> texts, String properties)
  {
    return new FlashAction(FlashActionType.MultiText,texts,properties);
  }
  
  public static FlashAction createEmpty(String properties)
  {
    return new FlashAction(FlashActionType.Text,"",properties);
  }
  
  public static FlashAction createUnknown(String input, String properties)
  {
    return new FlashAction(FlashActionType.Unknown,"Unknown action: ["+ input +"]",properties);
  }

  public static FlashAction createUrlImage(String urlFilename, String localFilename, String properties)
  {
    FlashAction action = new FlashAction(FlashActionType.Image,localFilename,properties);
    action.setProperty("url", urlFilename);
    return action; 
  }
  
  public static FlashAction createImage(String filename, String properties)
  {
    return new FlashAction(FlashActionType.Image,filename,properties);
  }
  
  public static FlashAction createUnknownImage(String input, String properties)
  {
    return new FlashAction(FlashActionType.Unknown,"Unknown image: ["+ input +"]",properties);
  }
  
  public static FlashAction createPlay(String filepath, String properties) 
  {
    return new FlashAction(FlashActionType.AudioPlay, filepath);
  }
  
  public static FlashAction createUrlPlay(String urlFilename, String localFilename, String properties)
  {
    FlashAction action = new FlashAction(FlashActionType.AudioPlay,localFilename,properties);
    action.setProperty("url", urlFilename);
    return action; 
  }
  
  public static FlashAction createStop() 
  {
    return new FlashAction(FlashActionType.AudioStop, null);
  }  

  public static FlashAction createVideo(String filepath, String properties)
  {
    return new FlashAction(FlashActionType.Video, filepath);
  }
  
  //``````````````````````
  // INTERFACE
  //``````````````````````   
  
  public void setProperty(String aKey, String aValue)
  {
    _properties.put(aKey, aValue);
  }
  
  public String propertyOf(String aKey)
  {
    return propertyOf(aKey,"");
  }
  
  public String propertyOf(String aKey, String defaultIfMissing)
  {
    String answer = _properties.get(aKey.toLowerCase());
    return answer == null ? defaultIfMissing : answer;
  }
  
  
  //``````````````````````
  // OBJECT INTERFACE
  //``````````````````````  
  
  public String toString()
  {
    String asString = "["+ Type +":"+ Data;

    if (_properties.size() > 0)
    {
      asString += " where "; 
    }
    
    for (Enumeration<String> e = _properties.keys() ; e.hasMoreElements() ;) {
      String aKey = e.nextElement();
      String myValue = propertyOf(aKey);
      asString += aKey + ":" + myValue + ";";
    }
    
    asString += "]";
    return asString;
  }
  
  public boolean equals(Object obj)
  {
    if (obj == null || !(obj instanceof FlashAction))
    {
      return false;
    }
    
    FlashAction compareTo = (FlashAction)obj;
    
    if (Type != compareTo.Type)
    {
      return false;
    }
    
    if (Data != null && !isEqual(Data,compareTo.Data))
    {
      return false;
    }
    
    if (Data == null && compareTo.Data != null)
    {
      return false;
    }
    
    if (_properties.size() != compareTo._properties.size())
    {
      return false;
    }
    
    for (Enumeration<String> e = _properties.keys() ; e.hasMoreElements() ;) {
      String aKey = e.nextElement();
      String myValue = propertyOf(aKey);
      String yourValue = compareTo.propertyOf(aKey);
      
      if (!myValue.equals(yourValue))
      {
        return false;
      }
    }    
    
    return true;
  }
  
  //``````````````````````
  // PRIVATE METHODS
  //``````````````````````   
  
  private void loadMultiProperties(String input)
  {
    if (input == null)
    {
      return;
    }
    
    int startIndex;
    while ((startIndex = input.indexOf("{")) != -1)
    {
      int endIndex = input.indexOf("}");
      if (endIndex == -1)
      {
        return;
      }
      String properties = input.substring(startIndex,endIndex+1);
      loadProperties(properties);
      input = input.substring(endIndex+1);
    }
    
    
    
    
    
    
    
  }
  
  private void loadProperties(String input)
  {
    input = input.substring(1,input.length()-1);
    String[] allProperties = input.split(";");
    for (int i=0; i<allProperties.length; i++)
    {
      String internalInput = allProperties[i];
      String[] keyValue = internalInput.split(":");
      if (keyValue.length == 2)
      {
        setProperty(keyValue[0].trim(), keyValue[1].trim());
      }
    }
  }
  
  private boolean isEqual(Object nonNullData, Object otherData)
  {
    if (otherData == null)
    {
      return false;
    }
    else if (nonNullData.getClass().equals(ArrayList.class) && otherData.getClass().equals(ArrayList.class))
    {
     
      ArrayList<?> one = (ArrayList<?>)nonNullData;
      ArrayList<?> compareTo = (ArrayList<?>)otherData;
      
      if (one.size() != compareTo.size())
      {
        return false;
      }
      else
      {
        for(int i=0; i<one.size(); i++)
        {
          if (!one.get(i).equals(compareTo.get(i)))
          {
            return false;
          }
        }
        return true;
      }
    }
    else
    {
      return nonNullData.equals(otherData);  
    }
  }

}
